#include "ImageFunctions.h"
#include <stdio.h>
#include <stdlib.h>
/**
 * Retorna a quantidade de pixels diferentes entre as duas imagens utilizando NEON
 * */
int image_diff_all_NEON(const unsigned char *yuv1, const unsigned char *yuv2,int width,int height){
	int i;
	const uint8_t *pointer1 = yuv1;
	const uint8_t *pointer2 = yuv2;
	int8x16_t resultado;
	uint8x8_t resultado_soma;
	int8x16_t zero = vdupq_n_u8(0);
	uint64x2_t scalarResult;
	uint8x16_t vetor_result;
	uint8x16_t v1;
	uint8x16_t v2;
	
	int iguais = 0;
	int bufferSize = width*height*2;
	for(i = 0; i<bufferSize;i+=16){
	
			v1 = vld1q_u8(pointer1);
			v2 = vld1q_u8(pointer2);
			resultado = vsubq_u8(v1,v2);
			vetor_result = vceqq_u8(resultado,zero);
			scalarResult = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(vetor_result)));	
			iguais += ((int)vgetq_lane_u64(scalarResult,0) + (int)vgetq_lane_u64(scalarResult,1))/255;
			pointer1+=16;
			pointer2+=16;
	}
	return (bufferSize - iguais);
}

int image_diff_all(const unsigned char *yuv1, const unsigned char *yuv2,int width,int height){
	int i;
	int bufferSize = width*height*2;
	int pixels = 0;
	for(i = 0; i<bufferSize;i++){
		pixels = yuv1[i] - yuv2[i];
	}
	return (bufferSize - pixels);
}

//retorna o numero de bytes diferentes
int image_diff_section(const unsigned char *yuv1, const unsigned char *yuv2,int first_offset, 
					int end_offset){
	int i;
	int pixels = 0;
	for(i = first_offset; i<end_offset;i++){
		if((yuv1[i] - yuv2[i]) != 0)
			pixels++;
	}
	//int bufferSize = width*height*2;
	//int part_size = (end_offset - first_offset) * 2;
	return pixels;
}

int image_diff_section_NEON(const unsigned char *yuv1, const unsigned char *yuv2,int first_offset, 
					int end_offset,int width,int height){
	int i;
	const uint8_t *pointer1 = yuv1;
	const uint8_t *pointer2 = yuv2;
	int8x16_t resultado;
	uint8x8_t resultado_soma;
	int8x16_t zero = vdupq_n_u8(0);
	uint64x2_t scalarResult;
	uint8x16_t vetor_result;
	uint8x16_t v1;
	uint8x16_t v2;
	
	int iguais = 0;
	int bufferSize = width*height*2;
	if((end_offset - first_offset) % 16 == 0){
		for(i = first_offset; i<end_offset;i+=16){
		
				v1 = vld1q_u8(pointer1);
				v2 = vld1q_u8(pointer2);
				resultado = vsubq_u8(v1,v2);
				vetor_result = vceqq_u8(resultado,zero);
				scalarResult = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(vetor_result)));	
				iguais += ((int)vgetq_lane_u64(scalarResult,0) + (int)vgetq_lane_u64(scalarResult,1))/255;
				pointer1+=16;
				pointer2+=16;
		}
		return (bufferSize - iguais);
	}else{
		printf("NAO E MULTIPLO");
		exit(0);
	}
}

int *getVerticalSectionOffset(int porcentagem, int width, int height){
	// [0] - first_offset
	// [1] - end_offset
	int result[2];
	int bytes_meio = (height/2) * width;
	int bytes = (width*height*porcentagem)/100;
	result[0] = bytes_meio - (bytes/2);
	result[1] = bytes_meio + (bytes/2);
	return result;
}

